import { Injectable } from '@nestjs/common';
import { CreateMenuDto } from './dto/create-menu.dto';
import { DataSource, Repository } from 'typeorm';
import { Menu } from 'src/database/entitys/menu.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { MenuRole } from 'src/database/entitys/menu-role.entity';
import { UserRole } from 'src/database/entitys/user-role.entity';

@Injectable()
export class MenuService {
  constructor(
    @InjectRepository(Menu)
    private readonly menuRepository: Repository<Menu>,
    @InjectRepository(MenuRole)
    private readonly menuRoleRepository: Repository<MenuRole>,
    @InjectRepository(UserRole)
    private readonly userRoleRepository: Repository<UserRole>,
    private readonly dataSource: DataSource
  ) {}

  /** 新增或修改菜单 */
  async create(createMenuDto: CreateMenuDto) {
    await this.menuRepository.save(createMenuDto);
  }

  /**查找通过菜单名称 */
  async findByName(title: string) {
    return await this.menuRepository.findOne({
      where: {
        title,
      },
    });
  }

  /** 查询所有菜单 */
  async findAll() {
    return this.menuRepository.find({
      order: {
        orderNo: 'ASC',
      },
    });
  }

  /** 查询所有菜单带权限 */
  async findAllWithPermissions(userId: number) {
    return this.menuRepository
      .createQueryBuilder('menu')
      .innerJoin(MenuRole, 'menuRole', 'menu.menuId = menuRole.menuId')
      .innerJoin(UserRole, 'userRole', 'menuRole.roleId = userRole.roleId')
      .where('userRole.userId = :userId', { userId })
      .distinct(true)
      .orderBy('menu.orderNo', 'ASC')
      .getMany();
  }

  /** 通过menuId查询菜单详情 */
  async findOne(menuId: number) {
    await this.menuRepository.findOneBy({ menuId });
  }

  /** 删除菜单 */
  async remove(menuId: number) {
    const queryRunner = this.dataSource.createQueryRunner();

    await queryRunner.connect();
    await queryRunner.startTransaction();

    try {
      await this.removeMenuRole(menuId);
      await this.menuRepository.delete(menuId);
      await this.removeChildren(menuId);
      await queryRunner.commitTransaction();
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /** 删除子菜单 */
  async removeChildren(menuId: number) {
    // 1.查询子菜单
    const children = await this.menuRepository.find({
      where: {
        parentId: menuId,
      },
    });

    if (children.length === 0) {
      return;
    }

    for (const item of children) {
      await this.removeChildren(item.menuId);
      await this.removeMenuRole(item.menuId);
    }

    await this.menuRepository.delete({ parentId: menuId });
  }

  /** 删除菜单角色关联关系 */
  async removeMenuRole(menuId: number) {
    return await this.menuRoleRepository.delete({ menu: { menuId } });
  }
}
